#! /usr/bin/env python3
import hashlib
import hmac
import datetime
import random
import time
import json
from random import randint
import sys
import argparse
import logging
import requests
import os


def hex_hmac_sha256(sign_key, signing_string):
    signed_bytes = hmac.new(bytes(sign_key, 'latin-1'), bytes(signing_string, 'latin-1'),
                            digestmod=hashlib.sha256).hexdigest()
    return signed_bytes


def getAuthHeader(request_method, api_uri, request_body, aKey, aKeyId):
    request_timestamp = time.strftime("%Y%m%dT%H%M%SZ", time.localtime(time.time() + time.timezone))
    nonce = randint(10000, 99999)

    signing_string = "%s\n%s\n%s\n%d\n%s\n%s" % (
    request_method.upper(), api_uri, request_timestamp, nonce, aKeyId, request_body)
    signature = hex_hmac_sha256(aKey, signing_string)

    authorization_val = "HMAC-SHA256 " + aKeyId + ":" + signature
    header = '{"Authorization":"%s", "x-sfd-date":"%s", "x-sfd-nonce":"%s"}' % (
    authorization_val, request_timestamp, nonce)
    # logger.info(header)
    return json.loads(header)


def callApi(request_method, api_server, api_uri, request_body):
    method = request_method.upper()
    if (method != "GET") and (method != "POST"):
        print("Unsupported HTTP Method! Exiting...")
        return None

    # for "GET" request, the URL's query parameters must be used as "request_body"
    # for generating AuthHeader
    authHeader = getAuthHeader(method, api_uri, request_body, aKey, aKeyId)
    api_url = "%s%s" % (api_server, api_uri)

    headers = authHeader
    headers["Content-Type"] = "application/json; charset=utf-8"
    # print(json.dumps(headers))

    if (method == "GET"):
        if (request_body != ""):
            # assemble the parameters in dictionary for requests.get()
            param_list = request_body.split('&')
            param_dict = {}
            for item in param_list:
                key, value = item.split('=')
                param_dict[key] = value
            ret = requests.get(api_url, headers=headers, params=param_dict)
        else:
            ret = requests.get(api_url, headers=headers)

    if (method == "POST"):
        ret = requests.post(api_url, headers=headers, data=request_body)

    # print(ret.url)
    return ret

def getCustomerIdBykey():
    method = "GET"
    api_uri = "/v1.2/customer/"
    api_server = "https://base-api.swiftfederation.com"

    ret = callApi(method, api_server, api_uri, '')

    parsed_output = ret.json()
    customerId = parsed_output['id']
    return customerId

def getCustomerId(domain):
    method = "POST"
    api_uri = "/v1.1/customer_id"
    api_server = "https://cdn-api.swiftfederation.com"

    request_body = {}
    request_body["domain"] = domain

    ret = callApi(method, api_server, api_uri, json.dumps(request_body))

    parsed_output = ret.json()
    customerId = parsed_output['customerId']
    if 0 == customerId:
        raise Exception("domain not exist")
    return customerId

def getDomainDetail(customerId, domain):
    method = "GET"
    api_uri = "/v1.0/customers/%s/domains" % customerId
    api_server = "https://cdn-api.swiftfederation.com"
    ret = callApi(method, api_server, api_uri, "")

    # logger.info("response header: %s", ret.headers)
    parsed_output = ret.json()
    body = json.dumps(parsed_output, indent=4)
    # logger.info(body)
    # print(body)
    for item in parsed_output:
        if item["name"] == domain:
            # print(">>> getDomainDetail Domain detail: %s" % json.dumps(item))
            return json.dumps(item)

    return "[]"


def getServiceId(domain):
    method = "POST"
    api_uri = "/v1.1/service_id"
    api_server = "https://cdn-api.swiftfederation.com"

    request_body = {}
    request_body["domain"] = domain

    ret = callApi(method, api_server, api_uri, json.dumps(request_body))

    parsed_output = ret.json()
    return parsed_output['serviceId']


def readfile(file_path):
    with open(file_path, 'r') as file:
        # 读取文件内容
        content = file.read()
    return content


def uploadCertificate(certname, certfile, keyfile):
    method = "POST"
    api_uri = "/v1.0/certificates"
    api_server = "https://cdn-api.swiftfederation.com"

    request_body = {}
    request_body["customerId"] = getCustomerIdBykey()
    request_body["name"] = certname
    request_body["type"] = 'san'
    request_body["certificate"] = readfile(certfile)
    request_body["privateKey"] = readfile(keyfile)

    ret = callApi(method, api_server, api_uri, json.dumps(request_body))
    parsed_output = ret.json()
    return parsed_output


def attachCertificate(certificateId, domain):
    method = "POST"
    api_uri = f"/v1.0/certificates/{certificateId}/services/{getServiceId(domain)}"
    api_server = "https://cdn-api.swiftfederation.com"

    ret = callApi(method, api_server, api_uri, '')
    parsed_output = ret.json()
    if len(parsed_output) == 5:
        return 0
    else:
        print(parsed_output)
        return 1


if __name__ == "__main__":

    description = """SwiftFederation Certificate command-line tool"""

    epilog = """Examples:"""

    parser = argparse.ArgumentParser(description=description, epilog=epilog,
                                     formatter_class=argparse.RawTextHelpFormatter)

    parser.add_argument('-i', '--access-key-id', action='store', dest='accesskeyid', required=True,
                        help="access key ID of customer's PARENT")
    parser.add_argument('-a', '--access-key', action='store', dest='accesskey', required=True,
                        help="access key of customer's PARENT")
    parser.add_argument('-d', '--domains', action='store', dest='domains', required=True,
                        help='domain name')
    parser.add_argument('-c', '--cert-file', action='store', dest='certfile', required=True,
                        help='cert file path')
    parser.add_argument('-k', '--key-file', action='store', dest='keyfile', required=True,
                        help='cert key file path')

    args = parser.parse_args()

    aKeyId = args.accesskeyid
    aKey = args.accesskey

    domains = args.domains

    certFile = args.certfile
    keyFile = args.keyfile


    certName = f"{domains[:30].replace(',', '_')}-{random.randint(1000, 9999)}"
    ret = uploadCertificate(certName, certFile, keyFile)
    # print(ret)
    certId = ret['id']

    for domain in domains.split(","):
        retv = attachCertificate(certId, domain)
        if retv != 0:
            break

    sys.exit(retv)

